package com.to.aboomy.bannersample.indicator;

import com.to.aboomy.banner.Indicator;
import com.to.aboomy.bannersample.slice.Indicator2AbilitySclice;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Text;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;

import static com.to.aboomy.banner.IndicatorView.INDICATOR_DASH;

/**
 * 渐变指示器
 *
 * @since 2021-08-07
 */
public class FillIndicatorView extends Component implements Indicator, Component.DrawTask, Component.EstimateSizeListener {
    private Context context;
    private RectFloat rectF = null;
    /*--------------- 核心控制点大小距离参数 ---------------*/
    private float indicatorRadius;
    private float indicatorRatio = 1.0f;
    private float indicatorSelectedRadius;
    private float indicatorSelectedRatio = 1.0f;
    private float indicatorSpacing;
    private Paint slidPaint;
    private Paint WPaint;
    private Paint TPaint;
    private Paint indicatorPaint = null;
    int displayWith = 0;
    private int pagerCount = 0;
    private int selectedPage = 0;
    private float offset;
    private float offsetPixels;
    private Color selectedColor = Color.RED;
    private Color unColor = Color.GRAY;
    /**
     * 是否开启自动循环
     */
    private boolean isAutoLoop = false;
    private AnimatorValue animatorValue;
    /**
     * 控制在banner中的位置
     */
    private DependentLayout.LayoutConfig params;

    public FillIndicatorView(Context context) {
        this(context, null, null);
        this.context = context;
    }

    public FillIndicatorView(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        displayWith = display.getAttributes().width;
        indicatorRadius = AttrHelper.fp2px(10f, context);
        indicatorSelectedRadius = AttrHelper.fp2px(10f, context);
        indicatorSpacing = AttrHelper.fp2px(10, context);
        // 设置测量组件的监听器
        rectF = new RectFloat();
        indicatorPaint = new Paint();
        indicatorPaint.setStrokeWidth(3);
        indicatorPaint.setStyle(Paint.Style.STROKE_STYLE);
        indicatorPaint.setColor(Color.GRAY);

        slidPaint = new Paint();
        slidPaint.setStyle(Paint.Style.FILLANDSTROKE_STYLE);
        slidPaint.setColor(Color.RED);

        WPaint = new Paint();
        WPaint.setStyle(Paint.Style.FILL_STYLE);
        WPaint.setColor(Color.WHITE);

        TPaint = new Paint();
        TPaint.setStyle(Paint.Style.FILL_STYLE);
        TPaint.setColor(Color.TRANSPARENT);
        addDrawTask(this);
        setEstimateSizeListener(this);
    }

    @Override
    public void initIndicatorCount(int pagerCount) {
        this.pagerCount = pagerCount;
        setVisibility(pagerCount > 1 ? VISIBLE : HIDE);
        postLayout();
    }

    @Override
    public Component getView() {
        return this;
    }

    @Override
    public DependentLayout.LayoutConfig getParams() {
        if (params == null) {
            params = new DependentLayout.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_CONTENT, 100);
            params.addRule(DependentLayout.LayoutConfig.ALIGN_PARENT_BOTTOM);
            params.setMarginTop(30);
        }
        return params;
    }

    @Override
    public void setAutoStau(Boolean isAuto) {
        this.isAutoLoop = isAuto;
    }

    @Override
    public void onPageSliding(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSlideStateChanged(int i) {

    }

    @Override
    public void onPageChosen(int position) {
        selectedPage = position;
        System.out.println("onPageChosen==" + position);
        offset = 0;
        if (animatorValue == null) {
            animatorValue = new AnimatorValue();
        }
        animatorValue.setDuration(200);
        animatorValue.setValueUpdateListener((animatorValue1, v) -> {
            offset = v;
            invalidate();
        });
        animatorValue.start();
        postLayout();
    }


    @Override
    public void onDraw(Component component, Canvas canvas) {
        indicatorPaint.setAntiAlias(true);
        if (pagerCount == 0) {
            return;
        }
        float midY = 30 / 2.0f + 0.5f;
        drawCircle(canvas, midY);
    }

    @Override
    public boolean onEstimateSize(int widthEstimateConfig, int heightEstimateConfig) {
        int width = Component.EstimateSpec.getSize(widthEstimateConfig);
        int height = Component.EstimateSpec.getSize(heightEstimateConfig);
        setEstimatedSize(
                Component.EstimateSpec.getChildSizeWithMode(width, width, EstimateSpec.NOT_EXCEED),
                Component.EstimateSpec.getChildSizeWithMode(height, height, Component.EstimateSpec.NOT_EXCEED)
        );
        return true;
    }

    /**
     * 画滚动轨迹的圆
     *
     * @param canvas canvas
     * @param midY   midY
     */
    private void drawCircle(Canvas canvas, float midY) {
        indicatorPaint.setStrokeWidth(3);
        // 画默认圆
        drawPagerCountCircle(canvas, midY);
        drawPagerCurrentCircle(canvas, midY); //画现在的圆
        drawPagerLastCircle(canvas, midY); //画上一个的圆

    }


    //画上一个的圆
    private void drawPagerLastCircle(Canvas canvas, float midY) {
        int currentpage = getLastPageIndex(selectedPage);
        float startCx = indicatorStartX(currentpage);
        float ratioIndicatorRadius = getRatioRadius();
        float left = startCx - ratioIndicatorRadius;
        float top = midY - indicatorRadius;
        float right = startCx + ratioIndicatorRadius;
        float bottom = midY + indicatorRadius;
        if (offset == 1.0) {
            //画灰色边框
            indicatorPaint.setStrokeWidth(0.5f);
            canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, (right - left) / 2, indicatorPaint);
            //画灰色内部
            canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, (right - left) / 2, TPaint);
        } else {
            float radius = (right - left) / 2 + 1;
            canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, radius, slidPaint);//红色的
            canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, radius * offset, WPaint);//b色的
        }

    }

    //画现在的圆
    private void drawPagerCurrentCircle(Canvas canvas, float midY) {
        float startCx = indicatorStartX(selectedPage);
        float ratioIndicatorRadius = getRatioRadius();
        float left = startCx - ratioIndicatorRadius;
        float top = midY - indicatorRadius;
        float right = startCx + ratioIndicatorRadius;
        float bottom = midY + indicatorRadius;
        rectF = new RectFloat(left, top, right, bottom);
        rectF.modify(left, top, right, bottom);
        canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, (right - left) / 2 + 2, slidPaint);//红色的
        float radius = (right - left) / 2 + 2;
        canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, radius * (1 - offset), WPaint);//白色的

    }

    /**
     * 画基础的圆
     *
     * @param canvas
     * @param midY
     */
    private void drawPagerCountCircle(Canvas canvas, float midY) {
        indicatorPaint.setColor(unColor);
        for (int i = 0; i < pagerCount; i++) {
            float startCx = indicatorStartX(i);
            float ratioIndicatorRadius = getRatioRadius();
            float left = startCx - ratioIndicatorRadius;
            float top = midY - indicatorRadius;
            float right = startCx + ratioIndicatorRadius;
            float bottom = midY + indicatorRadius;
            rectF = new RectFloat(left, top, right, bottom);
            rectF.modify(left, top, right, bottom);
            canvas.drawCircle(left + (right - left) / 2, getHeight()/2f, (right - left) / 2 + 2, indicatorPaint);
        }
    }

    /**
     * 计算下一个索引值
     *
     * @param selectedPage
     * @return
     */
    private int getLastPageIndex(int selectedPage) {
        int lastPageIndex = 0;
        if (selectedPage == 0) {
            lastPageIndex = pagerCount - 1;
        } else {
            lastPageIndex = selectedPage - 1;
        }
        return lastPageIndex;
    }

    private float indicatorStartX(int index) {
        float ratioRadius = getRatioRadius();
        float ratioSelectedRadius = getRatioSelectedRadius();
        float ratioIndicatorRadius = Math.max(ratioRadius, ratioSelectedRadius);
        float centerSpacing = ratioIndicatorRadius * 2.0f + indicatorSpacing - 10;
        float ssx = (displayWith - centerSpacing * pagerCount) / 2;
        float centerX = ratioIndicatorRadius + getPaddingLeft() + centerSpacing * index;
        /*
           为了适配INDICATOR_DASH样式， measure 中默认多增加了 ratioIndicatorRadius - ratioRadius 的高度和宽度
           除了INDICATOR_DASH样式下，其他样式需要增加indicatorSelectedRadius一半的距离，让位置居中。
         */
        return centerX + ((ratioIndicatorRadius - ratioRadius) / 2) + ssx;
    }

    /**
     * getRatioRadius
     *
     * @return float
     */
    private float getRatioRadius() {
        return indicatorRadius * indicatorRatio;
    }

    /**
     * getRatioSelectedRadius
     *
     * @return float
     */
    private float getRatioSelectedRadius() {
        return indicatorSelectedRadius * indicatorSelectedRatio;
    }


    /**
     * 设置选中的圆角，没有设置，默认和indicatorRadius值一致
     *
     * @param indicatorSelectedRadius 单位dp
     */
    public Indicator setIndicatorSelectedRadius(float indicatorSelectedRadius) {
        this.indicatorSelectedRadius = AttrHelper.vp2px(indicatorSelectedRadius, context);
        return this;
    }

    public Indicator setIndicatorColor(Color indicatorColor) {
        this.unColor = indicatorColor;
        return this;
    }

    public Indicator setIndicatorSelectorColor(Color indicatorSelectorColor) {
        this.selectedColor = indicatorSelectorColor;
        return this;
    }
}
